/**
 * 
 */
package com.easidea.tim.service.system.orgnization;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springside.core.service.EntityService;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.easidea.tim.action.ActionConstants;
import com.easidea.tim.dao.system.orgnization.DepartmentDao;
import com.easidea.tim.dao.system.orgnization.StaffCreditLimitDAO;
import com.easidea.tim.dao.system.orgnization.StaffDAO;
import com.easidea.tim.dao.system.orgnization.StaffTeamworkDao;
import com.easidea.tim.dao.system.permission.RoleDao;
import com.easidea.tim.dto.LoggedUserDTO;
import com.easidea.tim.entity.system.orgnization.Department;
import com.easidea.tim.entity.system.orgnization.Staff;
import com.easidea.tim.entity.system.orgnization.StaffCreditLimit;
import com.easidea.tim.entity.system.orgnization.StaffTeamwork;
import com.easidea.tim.entity.system.permission.Role;
import com.easidea.tim.util.DateUtil;
import com.easidea.tim.util.Page;
import com.opensymphony.xwork.ActionContext;

/**
 * @author Harrison
 * 
 */
public class StaffService extends EntityService<Staff, StaffDAO> {
	private static final Logger log = Logger.getLogger(StaffService.class);

	public static final Short STAFF_LOGON_SUCCESS = 1; // 登录成功
	public static final Short STAFF_LOGON_FAILURE_NOUSER = -1; // 用户名无效
	public static final Short STAFF_LOGON_FAILURE_PASS_ERROR = -2; // 口令错误
	public static final Short STAFF_LOGON_FAILURE_STATUS_ERROR = -3; // 状态无效
	public static final Short STAFF_LOGON_FAILURE_SYS_ERROR = 0; // 系统错误

	private StaffDAO staffDao;
	private DepartmentDao departmentDao;
	private StaffTeamworkDao staffTeamworkDao;

	private RoleDao roleDao;

	public void setStaffTeamworkDao(StaffTeamworkDao staffTeamworkDao) {
		this.staffTeamworkDao = staffTeamworkDao;
	}

	private StaffCreditLimitDAO staffCreditLimitDao;

	public void setDepartmentDao(DepartmentDao departmentDao) {
		this.departmentDao = departmentDao;
	}

	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}

	@Override
	public StaffDAO getEntityDao() {
		return staffDao;
	}

	/**
	 * @param staffDao
	 *            the staffDao to set
	 */
	public void setStaffDao(StaffDAO staffDao) {
		this.staffDao = staffDao;
	}
	public List<String> getTeamworkIdsByLoginUserId(Long loginUserId) {
		return this.staffDao.getTeamworkIdsByLoginUserId(loginUserId);
	}
	/**
	 * 用户登录，登录同时更新最后登录时间
	 * 
	 * @param staff
	 * @return
	 */
	public int staffLogin(String username, String password) {
		if (username != null && password != null) {
			Criteria cte = staffDao.createCriteria();
			cte.add(Restrictions.eq("username", username));
			cte.add(Restrictions.eq("password", password));
			cte.add(Restrictions.eq("status", Staff.STAFF_STATUS_ACTIVED));
			cte.setFetchSize(1);
			Staff loggedStaff = (Staff) cte.uniqueResult();
			if (loggedStaff != null && loggedStaff.getId() != null) {
				LoggedUserDTO loggedUser = genLoggedUserDTOFromStaff(loggedStaff); // 获取登录用户DTO
				ActionContext.getContext().getSession().put(
						ActionConstants.LOGGED_USER, loggedUser); // 不能在session中存放含有hibernate
				// session connection的对象，
				// 仅能存放无连接的DTO对象
				loggedStaff.setLastLogonTime(new Date());
				staffDao.merge(loggedStaff);
				return STAFF_LOGON_SUCCESS;
			} else {
				cte = staffDao.createCriteria();
				cte.add(Restrictions.eq("username", username));
				cte.setFetchSize(1);
				Object dbData = cte.uniqueResult();
				if (dbData != null) {
					Staff tmpStaff = (Staff) dbData;
					if (!tmpStaff.getStatus()
							.equals(Staff.STAFF_STATUS_ACTIVED))
						return STAFF_LOGON_FAILURE_STATUS_ERROR;
					return STAFF_LOGON_FAILURE_PASS_ERROR;
				} else {
					return STAFF_LOGON_FAILURE_NOUSER;
				}
			}
		} else {
			log.debug("[ERROR_CODE: 0]username or password is null !");
			return STAFF_LOGON_FAILURE_SYS_ERROR;
		}
	}

	public Staff doLogin(String username, String password) {
		String flag = "0";
		Criteria ca = this.createUnDeletedCriteria();
		if (username != null) {
			ca.add(Restrictions.eq("username", username));
		}
		if (password != null) {
			ca.add(Restrictions.eq("password", password));
		}
		ca.add(Restrictions.eq("status", Staff.STAFF_STATUS_ACTIVED));
		Staff staff = (Staff) ca.uniqueResult();
		if (staff != null) {
			Document document = load("d://change.xml");
			Node root = document.getDocumentElement();
			if (root.hasChildNodes()) {
				NodeList ftpnodes = root.getChildNodes();
				for (int i = 0; i < ftpnodes.getLength(); i++) {
					NodeList ftplist = ftpnodes.item(i).getChildNodes();
					for (int k = 0; k < ftplist.getLength(); k++) {
						Node subnode = ftplist.item(k);
						if (subnode.getNodeName() == "change") {
							flag = subnode.getFirstChild().getNodeValue();
						}
					}

				}
			}
			staff.setMemo(flag);
			staff.setLastLogonTime(new Date());
			this.staffDao.getHibernateTemplate().update(staff);
			return staff;
		}
		return null;
	}
	
	public static Document load(String filename) {
		Document document = null;
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse(new File(filename));
			document.normalize();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return document;
	}

	public List<Role> getAllRole() {
		return this.roleDao.getAllValid();
	}

	private boolean hasSameName(long id, String name) {
		boolean ret = false;
		Criteria ca = createUnDeletedCriteria();
		if (name != null && !name.equals("")) {
			ca.add(Restrictions.eq("username", name));
		}
		if (id != -1) {
			ca.add(Restrictions.ne("id", id));
		}
		if (ca.uniqueResult() != null) {
			ret = true;
		}
		return ret;
	}

	/**
	 * 创建员工信息
	 * 
	 * @param staff
	 * @return
	 */
	public String createOrUpdateStaff(Staff staff) {
		if (hasSameName(staff.getId(), staff.getUsername())) {
			return "ExistSameName";
		}
		try {
			if (staff.getId() == -1) {
				staffDao.getHibernateTemplate().save(staff);
			} else {
				staffDao.getHibernateTemplate().update(staff);
			}
			staffDao.getHibernateTemplate().update(staff);
		} catch (Exception e) {

			log.error("create  or update staff error! " + e.getMessage(), e);
			return "failure";
		}
		return "success";
	}

	/**
	 * 列取员工信息
	 * 
	 * @param staff
	 * @param startIndex
	 * @param pageSize
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Page listStaff(String name, Date dutyDate, long deptId,
			String email, Page page) {
		Criteria ca = this.listStaffCriteria(name, dutyDate, deptId, email);
		ca.setProjection(Projections.count("id"));
		Integer totalNum = (Integer) ca.uniqueResult();
		Criteria ca1 = this.listStaffCriteria(name, dutyDate, deptId, email);
		int startIndex = Page.getStartOfPage(page.getCurrentPageNo(), page
				.getPageSize());
		ca1.setFirstResult(startIndex);
		ca1.setMaxResults(page.getPageSize());
		List<Staff> ls = (List<Staff>) ca1.list();
		for (Staff sf : ls) {
			sf.getDepartment();
		}
		Page resultPage = new Page(startIndex, totalNum, page.getPageSize(), ls);
		resultPage.setCurrentPageNo(page.getCurrentPageNo());

		return resultPage;
	}

	/**
	 * 根据查询条件组织查询语句
	 * 
	 * @param name
	 * @param dutyDate
	 * @param deptId
	 * @param email
	 * @return
	 */
	private Criteria listStaffCriteria(String name, Date dutyDate, long deptId,
			String email) {
		Criteria ca = this.createUnDeletedCriteria();
		if (name != null && !name.equals("")) {
			ca.add(Restrictions.ilike("name", name, MatchMode.START));
		}
		if (dutyDate != null) {
			ca.add(Restrictions.between("dutyDate", DateUtil
					.getStartTime(dutyDate), DateUtil.getEndTime(dutyDate)));
		}
		if (deptId != -1) {
			ca.add(Restrictions.eq("department.id", deptId));
		}
		if (email != null && !email.equals("")) {
			ca.add(Restrictions.eq("email", email));
		}
		return ca;
	}

	@SuppressWarnings("unchecked")
	public List getTeamworks(Long id) {
		List teamworks = new ArrayList();
		teamworks.add(this.getXmlData());
		teamworks.add(this.getTeamworksById(id));
		return teamworks;
	}

	@SuppressWarnings("unchecked")
	public List<Staff> getTeamworksById(Long id) {
		List<Long> teamworkIds = this.staffTeamworkDao
				.getTeamworkIdByParentId(id);
		if (teamworkIds != null && teamworkIds.size() > 0) {
			String ids = "";
			for (Long teamworkId : teamworkIds) {
				ids += teamworkId + ",";
			}
			ids = ids.substring(0, ids.length() - 1);
			String hql = "select new com.easidea.tim.entity.system.orgnization.Staff(s.id,s.name,s.username)"
					+ " from "
					+ Staff.class.getName()
					+ " as s where s.deleted = 0 and id in (" + ids + ")";
			return this.staffDao.find(hql, null);
		}
		return null;
	}

	public String getXmlData() {
		StringBuffer xml = new StringBuffer();
		List<Department> allDept = departmentDao.getAllDepartmentList();
		// xml.append("<>");
		xml
				.append("<folder state='unchecked' label='组织人员信息' isBranch = 'true' type='root'  id='-1'> ");
		this.xmlData(xml, allDept);
		xml.append(" </folder>");
		// xml.append("</>");
		// System.out.println("xml Data:"+xml);
		return xml.toString();
	}

	private void xmlData(StringBuffer xml, List<Department> allDept) {
		for (Department dept : allDept) {
			xml.append("<folder state='unchecked' type='department' label='");
			xml.append(dept.getName());
			xml.append("'");
			List<Staff> staffs = staffDao.getStaffsByDeptId(dept.getId());
			boolean bstf = (staffs != null && staffs.size() > 0) ? true : false;
			boolean bdept = (dept.getSonList() != null && dept.getSonList()
					.size() > 0) ? true : false;

			if (bstf) {
				xml.append(" isBranch = 'true' id='");
				xml.append(dept.getId());
				xml.append("' ");
				xml.append(" >");
				for (Staff staff : staffs) {
					xml
							.append("<folder state='unchecked' type='staff' label='");
					xml.append(staff.getName());
					xml.append("'");
					xml.append(" isBranch = 'false' id='");
					xml.append(staff.getId());
					xml.append("' ");
					xml.append(" />");
				}
				if (!bdept) {
					xml.append(" </folder>");
				}
			}
			if (bdept) {
				if (!bstf) {
					xml.append(" isBranch = 'true' id='");
					xml.append(dept.getId());
					xml.append("' ");
					xml.append(" >");
				}
				xmlData(xml, dept.getSonList());
				xml.append(" </folder>");
			}
			if (!bstf && !bdept) {
				xml.append(" isBranch = 'false' id='");
				xml.append(dept.getId());
				xml.append("' ");
				xml.append(" />");
			}
		}
	}

	public boolean saveStaffTeamwork(Integer parentId, List<Integer> children,
			int recursionSearch) {
		int iRet = this.staffTeamworkDao
				.deleteStaffTeamworkByParentId(new Long(parentId));
		if (iRet < 0) {
			return false;
		}
		if (iRet >= 0 && children != null && children.size() > 0) {
			for (Integer childId : children) {
				StaffTeamwork teamwork = new StaffTeamwork();
				teamwork.setParentId(new Long(parentId));
				teamwork.setChildId(new Long(childId));

				this.staffTeamworkDao.save(teamwork);
			}
			Staff staff = getStaffById(parentId);
			staff.setRecursionSearch((short) recursionSearch);
			this.staffDao.getHibernateTemplate().update(staff);
		}
		return true;
	}

	


	/**
	 * 根据id获取员工信息
	 * 
	 * @param id
	 * @return
	 */
	public Staff getStaffById(long id) {
		return get(id);
	}

	/**
	 * 根据id更新deleted标志为1
	 * 
	 * @param id
	 * @return
	 */
	public boolean deleteEmployee(long id) {
		Staff staff = get(id);
		staff.setDeleted((short) 1);
		staff.setModifyTime(new Date());
		try {
			this.staffDao.getHibernateTemplate().update(staff);
		} catch (DataAccessException de) {
			de.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 根据姓名过滤员工信息
	 * 
	 * @param name
	 *            员工姓名
	 * @return
	 * @author Harrison
	 * @date 2009-12-03
	 */
	public List<Staff> filteStuff(String name) {
		List<Staff> rtnList = new ArrayList<Staff>();
		if (name != null && name.trim().length() > 0) {
			Criteria cte = staffDao.createUnDeletedCriteria();
			cte.add(Restrictions.ilike("name", name, MatchMode.ANYWHERE));
			cte.setFetchSize(10);
			rtnList = cte.list();
		}
		return rtnList;
	}

	/********************************************************************************/

	/**
	 * 通过Staff对象，创建LoggedUserDTO对象
	 * 
	 * @param staff
	 * @return
	 */
	private LoggedUserDTO genLoggedUserDTOFromStaff(Staff staff) {
		LoggedUserDTO dto = null;
		if (staff != null) {
			dto = new LoggedUserDTO();
			if (staff.getId() != null)
				dto.setId(staff.getId());
			if (staff.getName() != null)
				dto.setName(staff.getName());
			if (staff.getDepartment() != null)
				dto.setDepartmentName(staff.getDepartment().getName());
			if (staff.getLastLogonTime() != null)
				dto.setLastLoginTime(staff.getLastLogonTime());
			if (staff.getPosition() != null)
				dto.setPosition(staff.getPosition());
		}
		return dto;
	}

	/**
	 * 根据业务员id获取业务员额度信息
	 * 
	 * @param staffId
	 * @return
	 */
	public StaffCreditLimit getStaffCreditLimitByStaffId(long staffId) {
		return staffCreditLimitDao.getStaffCreditLimitByStaffId(staffId);
	}

	public String initStaffCreditLimit(long staffId, double initCreditLimit,
			String creator, long createId) {
		Staff staff = this.get(staffId);
		return staffCreditLimitDao.initStaffCreditLimit(staff, initCreditLimit,
				creator, createId);

	}

	public String modifyStaffCreditLimit(long staffId, double currentLimit,
			double modifylimit, String modifier, long modifyId) {
		return staffCreditLimitDao.modifyStaffCreditLimit(staffId,
				currentLimit, modifylimit, modifier, modifyId);
	}

	public void setStaffCreditLimitDao(StaffCreditLimitDAO staffCreditLimitDao) {
		this.staffCreditLimitDao = staffCreditLimitDao;
	}
	
	
	/**
	 * 提取当前销售人员的信用情况。处理时，系统需要根据销售人员ID提取个人的授信额度。
	 * 同时，提取该销售人员所直接管理的客户目前的欠款情况，扣除欠款为负数的内容，计算对应
	 * 销售人员当前整体的欠款情况，并作返回。
	 * @param staffId
	 * @return Map(String, Double)，其中的key为 {@link com.easidea.tim.entity.system.orgnization.StaffCreditLimit#CREDIT_LIMITATION_STAFF_CURRENT_VALUE}及
	 * 	{@link com.easidea.tim.entity.system.orgnization.StaffCreditLimit#CREDIT_LIMITATION_STAFF_CUSTOMER_VALUE}。同时需要注意返回对象为空，及是否存在对应的Key
	 */
	public Map<String, Double> getStaffCurrentCreditInfo(Long staffId){
		return staffCreditLimitDao.getStaffCurrentCreditInfo(staffId);
	}
	
	public Map<String, Double> getStaffCurrentCreditInfo(String creator){
		long staffId = staffDao.getStaffbyName(creator).getId();
		return staffCreditLimitDao.getStaffCurrentCreditInfo(staffId);
	}
	
	/**
	 * 修改员工口令
	 * @param userId
	 * @param pass
	 */
	public int updateEmpPass(Long userId, String pass){
		if(userId != null && StringUtils.isNotBlank(pass)){
			Staff staff = staffDao.get(userId);
			if(staff != null){
				staff.setPassword(pass);
				staffDao.merge(staff);
				return 1;
			}else{
				return -1;
			}
		}else{
			return 0;
		}
	}
	
}
